﻿using Microsoft.Xna.Framework;
using OTAPI;
using System;
using System.Collections.Generic;
using Terraria;
using Terraria.DataStructures;
using Terraria.ID;
using TShockAPI;

namespace TShock_AI
{
    public class NPC_STATE
    {
        public float[] state;
        public string[] message;
        public bool[] broadcastFlag;
        public Color color = Color.Purple;
        public NPC_STATE(float[] state)
        {
            this.state = state;
            this.message = new string[state.Length + 1];
            this.broadcastFlag = new bool[state.Length + 1];
            for (int i = 0; i < state.Length + 1; i++)
            {
                this.broadcastFlag[i] = false;
            }
        }
    }
    public class NPC_AI
    {
        public static NPC_AI[] NPC_Data = new NPC_AI[Main.npc.Length];
        public static Random random = new Random();

        public NPC npc;

        private NPC_STATE state;

        protected int State
        {
            get
            {
                for (int i = 0; i < state.state.Length; i++)
                {
                    if (npc.life / (float)npc.lifeMax > state.state[i])
                    {
                        return i;
                    }
                }
                return state.state.Length;
            }
        }

        protected string[] Message
        {
            set
            {
                state.message = value;
            }
        }

        protected Color MessageColor
        {
            set
            {
                state.color = value;
            }
        }

        public NPC_AI(NPC npc, float[] state)
        {
            this.npc = npc;
            this.state = new NPC_STATE(state);
            NPC_Data[npc.whoAmI] = this;
            if (npc.boss == true)
            {
                //DateTime now = DateTime.Now;
                //if (now.Hour >= 0 && now.Hour < 8)
                //{
                //    npc.life = npc.lifeMax *= 100;
                //    TSPlayer.All.SendMessage("你听见了震耳欲聋的怒吼！死期已到！", Color.Red);
                //    npc.StrikeNPC(0, 0, 0);
                //}
            }
        }

        public Projectile NewProjectile(Vector2 position, Vector2 velocity, int type, int damage, float knockBack, int owner = 255, float ai0 = 0.0f, float ai1 = 0.0f)
        {
            Projectile projectile = Main.projectile[Projectile.NewProjectile(npc.GetSpawnSourceForNPCFromNPCAI(), position, velocity, type, damage, knockBack, owner, ai0, ai1)];
            return projectile;
        }

        public virtual void OnAttackedPlayer(TSPlayer player, int damage)
        {
            npc.life += damage;
            if (npc.life > npc.lifeMax)
            {
                npc.life = npc.lifeMax;
            }
            npc.StrikeNPC(0, 0, 0);
        }

        public virtual void OnAttackedMe(int damage)
        {

        }

        public virtual HookResult OnPreAI()
        {
            return HookResult.Continue;
        }

        public virtual void OnPostAI()
        {

        }

        public virtual void OnKilled()
        {

        }

        protected void Broadcast()
        {
            int index = State;
            if (state.broadcastFlag[index] == false && index < state.message.Length)
            {
                if (state.message[index] == "")
                {
                    return;
                }
                TSPlayer.All.SendMessage(state.message[index], state.color);
                state.broadcastFlag[index] = true;
            }
        }
    }

    public class KingSlimeAI : NPC_AI
    {
        public static readonly float CooldownOfSkill0 = 200;
        public static readonly float CooldownOfSkill1 = 150;
        public static readonly float CooldownOfSkill2 = 200;

        public float skill0 = CooldownOfSkill0;
        public float skill1 = CooldownOfSkill1;
        public float skill2 = CooldownOfSkill2;

        public KingSlimeAI(NPC npc) : base(npc, new float[] { 0.8f, 0.6f, 0.4f })
        {
            MessageColor = Color.LightBlue;
            Message = new string[] { "", "寒风呼啸", "你感觉寒冷刺骨", "史莱姆王发怒了" };
        }

        public override void OnPostAI()
        {
            //Console.WriteLine($"{npc.ai[0]},{npc.ai[1]},{npc.ai[2]},{npc.ai[3]}");
            Broadcast();
            NPCAimedTarget target = npc.GetTargetData();
            if (npc.ai[0] > -200 && npc.ai[0] < -120)
            {
                Point tileCoordinates = npc.Bottom.ToTileCoordinates();
                int howMany = 20;
                int num4 = 1;
                tileCoordinates.X += npc.direction * 3;
                int num5 = (int)((npc.ai[0] / 2) + 101);
                int num6 = 4;
                int num7 = num5 / num6 * num6;
                int num8 = num7 + num6;
                if (num5 % num6 != 0)
                    num8 = num7;
                for (int whichOne = num7; whichOne < num8 && whichOne < howMany; ++whichOne)
                {
                    int xOffset = whichOne * num4;
                    npc.AI_123_Deerclops_TryMakingSpike(ref tileCoordinates, npc.direction, howMany, whichOne, xOffset);
                    npc.AI_123_Deerclops_TryMakingSpike(ref tileCoordinates, -npc.direction, howMany, whichOne, xOffset);
                }
            }
            switch (State)
            {
                case 0:
                    {
                        skill0--;
                        if (skill0 < 0 && npc.ai[0] != -120 && npc.ai[0] != -200)
                        {
                            var vector = new Vector2((target.Position.X - npc.Center.X) > 0 ? 1 : -1, -2);
                            npc.velocity.X += vector.X * random.Next(5, 12);
                            npc.velocity.Y += vector.Y * random.Next(1, 4);
                            skill0 = CooldownOfSkill0 + random.Next(120);
                            npc.netUpdate = true;
                        }
                    }
                    break;
                case 1:
                    {
                        skill0--;
                        skill1--;
                        if (skill0 < 0 && npc.ai[0] != -120 && npc.ai[0] != -200)
                        {
                            var vector = new Vector2((target.Position.X - npc.Center.X) > 0 ? 1 : -1, -2);
                            npc.velocity += (vector * random.Next(3, 7));
                            skill0 = CooldownOfSkill0 + random.Next(80);
                            npc.netUpdate = true;
                        }
                        if (skill1 < 0)
                        {
                            NewProjectile(npc.Center, Vector2.Zero, ProjectileID.CultistBossIceMist, 16, 32);
                            skill1 = CooldownOfSkill1 + random.Next(150);
                        }
                    }
                    break;
                case 2:
                    {
                        skill1--;
                        skill2--;
                        var vector = npc.DirectionTo(target.Position);
                        vector.Normalize();
                        vector *= 2.5f;
                        if (skill1 < 0)
                        {
                            NewProjectile(npc.Center, Vector2.Zero, ProjectileID.CultistBossIceMist, 16, 64);
                            skill1 = CooldownOfSkill1 + random.Next(120);
                        }
                        if (skill2 < 800 && skill2 % 40 == 0)
                        {
                            NewProjectile(npc.Center, vector, ProjectileID.FrostWave, 18, 64);
                        }
                        if (skill2 < 0)
                        {
                            skill2 = CooldownOfSkill2 + 1100;
                        }
                    }
                    break;
                case 3:
                    {
                        skill1--;
                        skill2--;
                        if (skill1 < 0 && skill2 == 1500)
                        {
                            NewProjectile(npc.Center, Vector2.One.RotatedBy(random.NextDouble() * Math.PI), ProjectileID.CultistBossIceMist, 8, 64);
                            NewProjectile(npc.Center, Vector2.One.RotatedBy(random.NextDouble() * Math.PI), ProjectileID.CultistBossIceMist, 8, 64);
                            NewProjectile(npc.Center + new Vector2(0, -6 * 16), Vector2.Zero, ProjectileID.CultistBossLightningOrb, 14, 64);
                            skill1 = CooldownOfSkill1 + random.Next(150);
                        }
                        var vector = npc.DirectionTo(target.Position);
                        vector.Normalize();
                        vector *= 2.25f;
                        if (skill2 <= 1000 && skill2 % 60 == 0)
                        {
                            NewProjectile(npc.Center, vector, ProjectileID.FrostWave, 16, 64);
                            NewProjectile(npc.Center, vector.RotatedBy(0.45), ProjectileID.FrostWave, 14, 64);
                            NewProjectile(npc.Center, vector.RotatedBy(-0.45), ProjectileID.FrostWave, 14, 64);
                        }
                        if (skill2 < 0)
                            skill2 = CooldownOfSkill2 + 1400;
                    }
                    break;
            }
        }

        public override void OnAttackedPlayer(TSPlayer player, int damage)
        {
            int number = random.Next(100);
            if (number < 33)
            {
                player.SetBuff(BuffID.Chilled, random.Next(20, 180));
            }
            else if (number < 66)
            {
                player.SetBuff(BuffID.Frozen, random.Next(20, 60));
            }
            base.OnAttackedPlayer(player, damage);
        }
    }

    public class EyeofCthulhu_DemonEyeAI : NPC_AI
    {
        public static readonly float CooldownOfSkill0 = 90;

        public float skill0 = CooldownOfSkill0;

        private int damage;

        public EyeofCthulhu_DemonEyeAI(NPC npc, int damage) : base(npc, new float[] { })
        {
            this.damage = damage;
        }
        public override HookResult OnPreAI()
        {
            return base.OnPreAI();
        }
        public override void OnPostAI()
        {
            skill0--;
            NPCAimedTarget target = npc.GetTargetData();
            var vector = npc.DirectionTo(target.Position + new Vector2(random.Next(-32, 32), random.Next(-32, 32)));
            if (skill0 < 0 && (vector.X * npc.velocity.X > 0) && npc.HasPlayerTarget)
            {
                var projectile = NewProjectile(npc.Center, vector * 6f, ProjectileID.PinkLaser, damage, 35);
                Projectile_AI.Projectile_Data[projectile.whoAmI] = new Projectile_AI(projectile);
                skill0 += CooldownOfSkill0 + random.Next(50);
            }
        }

        public override void OnAttackedPlayer(TSPlayer player, int damage)
        {
            if (random.Next(100) > 50)
            {
                player.SetBuff(BuffID.Cursed, 60);
            }
            base.OnAttackedPlayer(player, damage);
        }
    }

    public class EyeofCthulhuAI : NPC_AI
    {
        public static readonly float CooldownOfSkill0 = 150;
        public static readonly float CooldownOfSkill1 = 150;
        public static readonly float CooldownOfSkill2 = 500;

        public static readonly int ProjectileSpeedOfState3 = 5;

        public float skill0 = CooldownOfSkill0;
        public float skill1 = CooldownOfSkill1;
        public float skill2 = CooldownOfSkill2;

        public List<EyeofCthulhu_DemonEyeAI> children = new List<EyeofCthulhu_DemonEyeAI>(16);

        public EyeofCthulhuAI(NPC npc) : base(npc, new float[] { 0.66f, 0.5f, 0.3f })
        {
            Message = new string[] { "燃烧吧！无法熄灭的火焰", "你找到那颗子弹了吗", "", "你听到了震耳欲聋的吼叫" };
        }

        private void Spawn(int number, int damage)
        {
            for (int i = 0; i < children.Count; i++)
            {
                if (children[i].npc.active == false)
                {
                    children[i] = children[children.Count - 1];
                    children.RemoveAt(children.Count - 1);
                }
            }
            if (children.Count > 128)
            {
                return;
            }
            for (int i = 0; i < number; i++)
            {
                EyeofCthulhu_DemonEyeAI demonEye = new EyeofCthulhu_DemonEyeAI(Main.npc[NPC.NewNPC(npc.GetSpawnSourceForNPCFromNPCAI(), (int)npc.Bottom.X + random.Next(-32, 32), (int)npc.Bottom.Y, NPCID.DemonEye)], damage);
                children.Add(demonEye);
            }
        }

        public override void OnPostAI()
        {
            Broadcast();
            NPCAimedTarget target = npc.GetTargetData();

            if (npc.ai[0] == 1 && npc.ai[1] % 2 == 0)
            {
                NewProjectile(npc.Bottom, npc.rotation.ToRotationVector2() * 13, ProjectileID.CursedFlameHostile, 20, 25);
            }

            if (State == 0)
            {
                if (random.Next(4) == 1)
                {
                    npc.velocity += Vector2.Normalize(npc.velocity);
                    npc.netUpdate = true;
                }
            }

            switch (State)
            {
                case 0:
                    {
                        skill0--;
                        if (skill0 < 0 && npc.ai[1] == 0)
                        {
                            var vector = npc.DirectionTo(target.Position);
                            if (npc.ai[2] == 40)
                            {
                                NewProjectile(npc.Bottom, vector * 15, ProjectileID.CursedFlameHostile, 18, 5);
                            }
                            if (npc.ai[2] == 80)
                            {
                                NewProjectile(npc.Bottom, vector * 17, ProjectileID.CursedFlameHostile, 20, 5);
                            }
                            else if (npc.ai[2] == 100)
                            {
                                NewProjectile(npc.Bottom, vector * 20, ProjectileID.CursedFlameHostile, 22, 5);
                            }
                            else if (npc.ai[2] == 110)
                            {
                                NewProjectile(npc.Bottom, vector * 21, ProjectileID.CursedFlameHostile, 23, 5);
                            }
                            else if (npc.ai[2] == 120)
                            {
                                NewProjectile(npc.Bottom, vector * 22, ProjectileID.CursedFlameHostile, 25, 5);
                                skill0 = CooldownOfSkill0 + random.Next(100);
                                npc.ai[2] = 100;
                            }
                        }
                    }
                    break;
                case 1:
                    {
                        skill0--;
                        if (skill0 < 0 && npc.ai[1] == 0)
                        {
                            var vector = npc.DirectionTo(target.Position);
                            if (npc.ai[2] == 120)
                            {
                                NewProjectile(npc.Bottom, (vector) * 25, ProjectileID.CursedFlameHostile, 22, 25);
                                NewProjectile(npc.Bottom, (vector.RotatedBy(0.1)) * 23, ProjectileID.CursedFlameHostile, 18, 25);
                                NewProjectile(npc.Bottom, (vector.RotatedBy(-0.1)) * 23, ProjectileID.CursedFlameHostile, 18, 25);
                            }
                            if (npc.ai[2] == 135)
                            {
                                NewProjectile(npc.Bottom, (vector) * 25, ProjectileID.CursedFlameHostile, 22, 25);
                                NewProjectile(npc.Bottom, (vector.RotatedBy(0.1)) * 23, ProjectileID.CursedFlameHostile, 18, 25);
                                NewProjectile(npc.Bottom, (vector.RotatedBy(-0.1)) * 23, ProjectileID.CursedFlameHostile, 18, 25);
                            }
                            if (npc.ai[2] == 150)
                            {
                                NewProjectile(npc.Bottom, (vector) * 27, ProjectileID.CursedFlameHostile, 24, 25);
                                NewProjectile(npc.Bottom, (vector.RotatedBy(0.1)) * 25, ProjectileID.CursedFlameHostile, 20, 25);
                                NewProjectile(npc.Bottom, (vector.RotatedBy(-0.1)) * 25, ProjectileID.CursedFlameHostile, 20, 25);
                                skill0 = CooldownOfSkill0;
                                npc.ai[2] = 100;
                                Spawn(2, 16);
                            }
                        }
                    }
                    break;
                case 2:
                    {
                        skill1--;
                        if (skill1 < 0 && npc.ai[1] == 0)
                        {
                            Spawn(3, 20);
                            skill1 = CooldownOfSkill1 + random.Next(50);
                        }
                    }
                    break;
                case 3:
                    {
                        skill1--;
                        skill2--;
                        if (skill1 < 0)
                        {
                            Spawn(6, 25);
                            skill1 = CooldownOfSkill1;
                        }
                        if (skill2 < 0 && npc.ai[1] == 4 && npc.ai[3] == 4)
                        {
                            npc.ai[3] = 0;
                            skill2 = CooldownOfSkill2;
                        }
                    }
                    break;
                default:
                    break;
            }
        }

        public override void OnAttackedPlayer(TSPlayer player, int damage)
        {
            if (random.Next(100) < 15)
            {
                player.SetBuff(BuffID.Confused, 120);
            }
            if (random.Next(100) < 30)
            {
                player.SetBuff(BuffID.Slow, 120);
            }
            if (random.Next(100) < 60)
            {
                player.SetBuff(BuffID.CursedInferno, 120);
            }
            base.OnAttackedPlayer(player, damage);
        }
    }


    public class WallofFleshEyeAI : NPC_AI
    {
        public static readonly float CooldownOfSkill0 = 140;

        public float skill0 = CooldownOfSkill0;

        public WallofFleshEyeAI(NPC npc) : base(npc, new float[] { 0.8f, 0.5f, 0.25f })
        {
        }
        public override void OnPostAI()
        {
            skill0--;
            if (skill0 < 0)
            {
                NPCAimedTarget target = npc.GetTargetData();
                var vector = npc.DirectionTo(target.Position);
                switch (State)
                {
                    case 0:
                        NewProjectile(npc.Center, vector * 8f, ProjectileID.EyeLaser, 12, 5);
                        skill0 += CooldownOfSkill0 + random.Next(100);
                        break;
                    case 1:
                        NewProjectile(npc.Center, vector * 9f, ProjectileID.EyeLaser, 15, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(-0.1) * 8f, ProjectileID.EyeLaser, 12, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(0.1) * 8f, ProjectileID.EyeLaser, 12, 5);
                        skill0 += CooldownOfSkill0 + random.Next(80);
                        break;
                    case 2:
                        NewProjectile(npc.Center, vector * 9f, ProjectileID.EyeLaser, 25, 20);
                        NewProjectile(npc.Center, vector.RotatedBy(0.1) * 8f, ProjectileID.EyeLaser, 20, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(-0.1) * 8f, ProjectileID.EyeLaser, 20, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(0.2) * 6f, ProjectileID.EyeLaser, 20, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(-0.2) * 6f, ProjectileID.EyeLaser, 20, 5);
                        skill0 += CooldownOfSkill0 + random.Next(30);
                        break;
                    case 3:
                        NewProjectile(npc.Center, vector * 15f, ProjectileID.EyeLaser, 30, 20);
                        NewProjectile(npc.Center, vector.RotatedBy(0.1) * 13f, ProjectileID.EyeLaser, 25, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(-0.1) * 13f, ProjectileID.EyeLaser, 25, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(0.2) * 10f, ProjectileID.EyeLaser, 25, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(-0.2) * 10f, ProjectileID.EyeLaser, 25, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(0.1) * 10f, ProjectileID.EyeLaser, 25, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(-0.1) * 10f, ProjectileID.EyeLaser, 25, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(0.2) * 10f, ProjectileID.EyeLaser, 25, 5);
                        NewProjectile(npc.Center, vector.RotatedBy(-0.2) * 10f, ProjectileID.EyeLaser, 25, 5);
                        skill0 += CooldownOfSkill0;
                        break;
                }
            }
        }
    }

    public class WallofFleshAI : NPC_AI
    {
        public static readonly float CooldownOfSkill0 = 150;

        public float skill0 = CooldownOfSkill0;

        public WallofFleshAI(NPC npc) : base(npc, new float[] { 0.5f, 0, 2f })
        {

        }

        public override void OnPostAI()
        {
            skill0--;
            NPCAimedTarget target = npc.GetTargetData();
            var vector = npc.DirectionTo(target.Position);
            if (skill0 < 0)
            {
                switch (State)
                {
                    case 0:
                        NewProjectile(npc.Center, vector * 13, ProjectileID.CultistBossFireBall, 28, 15);
                        skill0 = CooldownOfSkill0 + random.Next(50);
                        break;
                    case 1:
                        NewProjectile(npc.Center, vector * 20, ProjectileID.CultistBossFireBall, 40, 30);
                        skill0 = CooldownOfSkill0;
                        break;
                    case 2:
                        NewProjectile(npc.Center, vector * 26, ProjectileID.CultistBossFireBall, 66, 60);
                        skill0 = CooldownOfSkill0 - 20;
                        break;
                    default:
                        break;
                }
            }
        }
    }


    public class SkeletronHeadAI_SurrandAI : NPC_AI
    {
        public SkeletronHeadAI master;
        public SkeletronHeadAI_SurrandAI(NPC npc, SkeletronHeadAI master) : base(npc, new float[] { })
        {
            this.master = master;
        }

        public override HookResult OnPreAI()
        {
            if (npc.life <= 0)
            {
                npc.active = false;
                return HookResult.Cancel;
            }
            if (master.npc.active == false)
            {
                npc.active = false;
                return HookResult.Continue;
            }
            return HookResult.Cancel;
        }

        public void MoveTo(Vector2 position)
        {
            Vector2 discount = npc.position - position;
            npc.velocity = npc.position.DirectionTo(position) * master.npc.velocity.Length() * discount.Length() * 0.04f;
            npc.netUpdate = true;
        }

        public void Shoot(Vector2 veclocity, int id, int damage)
        {
            NewProjectile(npc.Center, veclocity, id, damage, 24);
        }

    }
    public class SkeletronHeadAI : NPC_AI
    {
        public List<SkeletronHeadAI_SurrandAI> surrandAIs = new List<SkeletronHeadAI_SurrandAI>();

        public SkeletronHeadAI(NPC npc) : base(npc, new float[] { 0.8f, 0.5f, 0.3f })
        {

        }

        public bool flag = false;
        public float rotate = 0.0f;
        public override void OnPostAI()
        {
            float discount = 32f;
            var count = 4;
            switch (State)
            {
                case 0:
                    {
                        discount = 3; count = 8;
                        if (random.Next(120) == 0)
                        {
                            for (int i = 0; i < surrandAIs.Count; i++)
                            {
                                surrandAIs[i].Shoot(Vector2.UnitY.RotatedBy(Math.PI * 2.0 / surrandAIs.Count * i + rotate) * 5, ProjectileID.CursedFlameHostile, 15);
                            }
                        }
                    }
                    break;
                case 1:
                    {
                        discount = 7; count = 10;
                        if (random.Next(60) == 0)
                        {
                            for (int i = 0; i < surrandAIs.Count; i++)
                            {
                                surrandAIs[i].Shoot(Vector2.UnitY.RotatedBy(Math.PI * 2.0 / surrandAIs.Count * i + rotate) * 6, ProjectileID.CursedFlameHostile, 20);
                            }
                        }
                        break;
                    }
                case 2:
                    {
                        discount = 12; count = 12;
                        if (random.Next(200) == 0)
                        {
                            for (int i = 0; i < surrandAIs.Count; i++)
                            {
                                surrandAIs[i].Shoot(Vector2.UnitY.RotatedBy(Math.PI * 2.0 / surrandAIs.Count * i + rotate) * 3, ProjectileID.Shadowflames, 13);
                            }
                        }
                    }
                    break;
                case 3:
                    {
                        discount = 4; count = 12;
                        if (random.Next(60) == 0)
                        {
                            for (int i = 0; i < surrandAIs.Count; i++)
                            {
                                surrandAIs[i].Shoot(Vector2.UnitY.RotatedBy(Math.PI * 2.0 / surrandAIs.Count * i + rotate) * 4.5f, ProjectileID.Shadowflames, 18);
                            }
                        }
                    }
                    break;
            }
            if (surrandAIs.Count < count && random.Next(60) == 0)
            {
                SkeletronHeadAI_SurrandAI cursedSkull = new SkeletronHeadAI_SurrandAI(Main.npc[NPC.NewNPC(npc.GetSpawnSourceForNPCFromNPCAI(), (int)npc.Center.X, (int)npc.Center.Y, NPCID.CursedSkull)], this);
                surrandAIs.Add(cursedSkull);
            }
            for (int i = surrandAIs.Count - 1; i >= 0; i--)
            {
                if (surrandAIs[i].npc.active == false)
                {
                    surrandAIs.RemoveAt(i);
                }
                else
                {
                    surrandAIs[i].MoveTo(npc.Center + Vector2.UnitY.RotatedBy(Math.PI * 2.0 / surrandAIs.Count * i + rotate) * 16 * discount);
                }
            }
            rotate += 0.002f;
        }
    }

    public class SkeletronHandAI : NPC_AI
    {
        public static readonly float CooldownOfSkill0 = 30;

        public float skill0 = CooldownOfSkill0;

        public SkeletronHandAI(NPC npc) : base(npc, new float[] { })
        {
        }
        public override void OnPostAI()
        {
            skill0--;
            if (skill0 < 0 && npc.ai[3] != 0 && npc.ai[3] < 10)
            {
                Projectile projectile = NewProjectile(npc.Center, Vector2.One, ProjectileID.SandnadoHostile, 25, 0);
                Projectile_AI.Projectile_Data[projectile.whoAmI] = new SandnadoHostile(projectile, npc);
                skill0 = CooldownOfSkill0;
            }
        }
    }



    public class EaterofWorldsBodyAI : NPC_AI
    {
        public EaterofWorldsBodyAI(NPC npc) : base(npc, new float[] { })
        {
            npc.ai[2] = random.Next(1, 2);
        }
        public override void OnPostAI()
        {
            if (EaterofWorldsHeadAI.kingHead.active == false && EaterofWorldsHeadAI.isKilled == false)
            {
                npc.velocity.Y += 1.5f;
                npc.netUpdate = true;
            }
        }
    }

    public class EaterofWorldsHeadAI : NPC_AI
    {
        public static NPC kingHead;
        public static bool isKilled;

        public static readonly float CooldownOfSkill0 = 350;

        public float skill0 = 0;

        public EaterofWorldsHeadAI(NPC npc) : base(npc, new float[] { })
        {
            kingHead = npc;
            isKilled = false;
            TSPlayer.All.SendMessage("你发现这个怪物的第一颗头颅上镌刻着一个亵渎神圣的古老符号", Color.DarkOrchid);
            TSPlayer.All.SendMessage("这个符号所带来的源源不断的力量，正在不断的壮大着它的军团", Color.DarkOrchid);
            NPC.NewNPC(npc.GetSpawnSourceForNPCFromNPCAI(), (int)npc.position.X, (int)npc.position.Y, NPCID.EaterofWorldsBody);
        }

        public override void OnPostAI()
        {
            skill0--;
            if (skill0 < 0)
            {
                npc.velocity *= 1.8f;
                skill0 = CooldownOfSkill0 + random.Next(100);
                NPC.NewNPC(npc.GetSpawnSourceForNPCFromNPCAI(), (int)npc.position.X, (int)npc.position.Y, NPCID.EaterofWorldsBody);

            }
        }
        public override void OnKilled()
        {
            TSPlayer.All.SendMessage("神圣不容被亵渎", Color.DarkOrchid);
            isKilled = true;
        }
        public override void OnAttackedPlayer(TSPlayer player, int damage)
        {
            player.SetBuff(20, 200);
            base.OnAttackedPlayer(player, damage);
        }
    }

    public class AntlionAI : NPC_AI
    {
        public AntlionAI(NPC npc) : base(npc, new float[] { })
        {
        }
        public override void OnPostAI()
        {
            NPCAimedTarget target = npc.GetTargetData();
            if (npc.ai[0] != 0 && npc.ai[0] % 15 == 0)
            {
                var vector = npc.DirectionTo(target.Position);
                vector += new Vector2((float)(random.NextDouble() - 0.5f), (float)(random.NextDouble() - 0.5f)) * 0.5f;
                NewProjectile(npc.Center, vector * random.Next(12, 18), ProjectileID.SandBallFalling, 13, 64);
            }
        }
    }

    public class DeerclopsAI : NPC_AI
    {
        public static readonly float CooldownOfSkill0 = 350;

        public float skill0 = 0;

        public DeerclopsAI(NPC npc) : base(npc, new float[] { 0.6f, 0.3f })
        {
            MessageColor = Color.SkyBlue;
            Message = new string[] { "远方的巨兽将会摧毁你所拥有的一切", "冰雪从天而降", "你将受到灭顶之灾" };
        }

        public override void OnPostAI()
        {
            Broadcast();
            skill0++;
            NPCAimedTarget target = npc.GetTargetData();

            if (npc.ai[0] == 6)
            {
                npc.life += 2;
                npc.StrikeNPC(0, 0, 0);
            }
            switch (State)
            {
                case 0:
                    {
                        if (npc.ai[0] == 5 && npc.ai[1] == 59)
                        {
                            if (Main.netMode != 1)
                            {
                                for (int index = 0; index < 3; ++index)
                                {
                                    Projectile.RandomizeInsanityShadowFor(Main.player[npc.target], true, out Vector2 spawnposition, out Vector2 spawnvelocity, out float ai0, out float ai1);
                                    NewProjectile(spawnposition, spawnvelocity, 965, 15, 0, Main.myPlayer, ai0, ai1);
                                }
                            }

                        }
                    }
                    break;
                case 1:
                    {
                        if (npc.ai[0] == 1 && npc.ai[1] == 30)
                        {
                            Point tileCoordinates = npc.Top.ToTileCoordinates();
                            for (int whichOne = 5; whichOne < 20; ++whichOne)
                                npc.AI_123_Deerclops_ShootRubbleUp(ref target, ref tileCoordinates, 20, 1, 200, whichOne);
                            if (random.Next(1) == 0 && npc.ai[1] == 79)
                            {
                                npc.ai[0] = 5;
                                npc.ai[1] = 0;
                            }

                        }
                        else if (npc.ai[0] == 5 && npc.ai[1] == 59)
                        {
                            if (Main.netMode != 1)
                            {
                                for (int index = 0; index < 8; ++index)
                                {
                                    Vector2 spawnposition;
                                    Vector2 spawnvelocity;
                                    float ai0;
                                    float ai1;
                                    Projectile.RandomizeInsanityShadowFor(Main.player[npc.target], true, out spawnposition, out spawnvelocity, out ai0, out ai1);
                                    NewProjectile(spawnposition, spawnvelocity, 965, 15, 0, Main.myPlayer, ai0, ai1);
                                }
                            }

                        }
                        if (skill0 >= 7)
                        {
                            NewProjectile(target.Position + new Vector2(random.Next(-16 * 96, 16 * 96), -16 * 48), Vector2.UnitY, ProjectileID.IceSpike, 3, 0);
                            skill0 = 0;
                        }
                    }
                    break;
                case 2:
                    {
                        if (npc.ai[0] == 1 && npc.ai[1] == 30)
                        {
                            Point tileCoordinates = npc.Top.ToTileCoordinates();
                            for (int whichOne = 5; whichOne < 20; ++whichOne)
                                npc.AI_123_Deerclops_ShootRubbleUp(ref target, ref tileCoordinates, 20, 1, 200, whichOne);
                            if (random.Next(1) == 0 && npc.ai[1] == 79)
                            {
                                npc.ai[0] = 5;
                                npc.ai[1] = 0;
                            }

                        }
                        else if (npc.ai[0] == 5 && npc.ai[1] == 59)
                        {
                            if (Main.netMode != 1)
                            {
                                for (int index = 0; index < 8; ++index)
                                {
                                    Vector2 spawnposition;
                                    Vector2 spawnvelocity;
                                    float ai0;
                                    float ai1;
                                    Projectile.RandomizeInsanityShadowFor(Main.player[npc.target], true, out spawnposition, out spawnvelocity, out ai0, out ai1);
                                    NewProjectile(spawnposition, spawnvelocity, 965, 15, 0, Main.myPlayer, ai0, ai1);
                                }
                            }

                        }
                        if (skill0 >= 3)
                        {
                            NewProjectile(target.Position + new Vector2(random.Next(-16 * 64, 16 * 64), -16 * 64), Vector2.UnitY * 3f, ProjectileID.IceSpike, 12, 5);
                            skill0 = 0;
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    }

    public class QueenBeeAI : NPC_AI
    {
        public QueenBeeAI(NPC npc) : base(npc, new float[] { })
        {

        }
        public override void OnPostAI()
        {
            NPCAimedTarget target = npc.GetTargetData();
            switch (npc.ai[0])
            {
                case 0:
                    if (random.Next(20) == 0)
                    {
                        var vector = npc.DirectionTo(target.Position);
                        vector.Normalize();
                        NewProjectile(npc.Center, vector, ProjectileID.DemonSickle, 15, 32);
                    }
                    break;
                case 1:
                    if (random.Next(10) == 0)
                    {
                        var vector = npc.DirectionTo(target.Position);
                        vector.Normalize();
                        NewProjectile(npc.Center, vector, ProjectileID.DemonSickle, 20, 32);
                    }
                    break;
                case 2:
                    if (random.Next(6) == 0)
                    {
                        NewProjectile(npc.Bottom, Vector2.UnitY.RotateRandom(Math.PI / 2) * -8, ProjectileID.QueenBeeStinger, 12, 1);
                    }
                    break;
                case 3:
                    if (npc.ai[1] % 12 == 0)
                    {
                        NewProjectile(npc.position - new Vector2(random.Next(16 * -64, 16 * 64), 16 * 24), Vector2.UnitY * -3, ProjectileID.QueenBeeStinger, 20, 1);
                    }
                    break;
                default:
                    break;
            }
        }
    }

    public class BrainofCthulhuAI : NPC_AI
    {
        public BrainofCthulhuAI(NPC npc) : base(npc, new float[] { 0.9f, 0.5f })
        {
            this.npc = npc;
            MessageColor = Color.Green;
            Message = new string[] { "你的身体里包含着创造生命的力量", "火焰在你的身体里燃烧", "你的头脑开始变得麻木" };
        }
        public override void OnPostAI()
        {
            Broadcast();
        }
        public override void OnAttackedPlayer(TSPlayer player, int damage)
        {
            if (State == 1)
            {
                player.SetBuff(BuffID.OnFire, random.Next(120, 500));
                player.SetBuff(BuffID.Tipsy, random.Next(120, 220));
            }
            if (State == 2)
            {
                player.SetBuff(BuffID.Slow, random.Next(60, 240));
                player.SetBuff(BuffID.Confused, random.Next(60, 240));
                player.SetBuff(BuffID.Darkness, random.Next(20, 80));
            }
            base.OnAttackedPlayer(player, damage);
        }
    }

    public class CreeperAI : NPC_AI
    {
        public CreeperAI(NPC npc) : base(npc, new float[] { })
        {
            this.npc = npc;
        }

        public override void OnKilled()
        {
            NewProjectile(npc.position, Vector2.UnitY * -1 - new Vector2((float)(random.NextDouble() - 0.5f), 0) * 24, ProjectileID.BloodShot, 18, 12);
            NewProjectile(npc.position, Vector2.UnitY * -1 - new Vector2((float)(random.NextDouble() - 0.5f), 0) * 24, ProjectileID.BloodShot, 25, 12);
            NewProjectile(npc.position, Vector2.UnitY * -1 - new Vector2((float)(random.NextDouble() - 0.5f), 0) * 24, ProjectileID.BloodShot, 18, 12);
            base.OnKilled();
        }

        public override void OnAttackedPlayer(TSPlayer player, int damage)
        {
            npc.life += damage;
            npc.StrikeNPC(0, 0, 0);
            if (npc.life > npc.lifeMax)
            {
                new CreeperAI(
                Main.npc[NPC.NewNPC(
                    npc.GetSpawnSourceForNPCFromNPCAI(), (int)npc.Bottom.X, (int)npc.Bottom.Y, NPCID.Creeper)]);
            }
            else if (random.Next(100) < 25)
            {
                CreeperAI creeper = new CreeperAI(
                Main.npc[NPC.NewNPC(
                    npc.GetSpawnSourceForNPCFromNPCAI(), (int)npc.Bottom.X, (int)npc.Bottom.Y, NPCID.Creeper)]);
            }
        }

        public override void OnPostAI()
        {
            if (random.Next(5) == 1)
            {
                npc.velocity += Vector2.Normalize(npc.velocity) / 5;
                npc.netUpdate = true;
            }
        }
    }
}
